package com.pachong.android.framework.httprequest.volleyadaptee;

import android.content.Context;
import android.text.TextUtils;

import com.android.volley.AuthFailureError;
import com.android.volley.NetworkResponse;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonRequest;
import com.android.volley.toolbox.StringRequest;
import com.pachong.android.framework.httprequest.HttpRequest;
import com.pachong.android.framework.httprequest.IHttpRequest;
import com.pachong.android.framework.httprequest.IResponseDataParser;
import com.pachong.android.framework.httprequest.UrlParams;
import com.pachong.android.framework.httprequest.responsecallbacks.RequestListener;
import com.pachong.android.frameworkbase.utils.SLog;

import org.json.JSONObject;

import java.util.HashMap;
import java.util.Map;


public class VolleyHttp implements IHttpRequest {

    private Context mContext;

    public VolleyHttp(Context context) {
        mContext = context;
    }

    @Override
    public void get(String url, UrlParams params, final RequestListener cb) {
        get(url, params, null, cb);
    }

    @Override
    public void get(String url, UrlParams params, final Map<String, String> headParams, final RequestListener cb) {
        String paramUrl = UrlParams.getUrlWithQueryString(url, params);
        SLog.e(HttpRequest.TAG, paramUrl);
        StringRequest request = new StringRequest(Request.Method.GET, paramUrl, new XResponseListener<String>(cb), new XErrorResponseListener(cb)) {
            @Override
            public Map<String, String> getHeaders() throws AuthFailureError {
                HashMap<String, String> headers = new HashMap<String, String>();
                headers.put("Accept", "application/json");
                headers.put("Content-Type", "application/json; charset=UTF-8");
                if (headParams != null && headParams.size() > 0) {
                    headers.putAll(headParams);
                }
                return headers;
            }

            @Override
            protected Response<String> parseNetworkResponse(NetworkResponse response) {
                return ResponseHelper.parseNetworkResponse2String(response);
            }
        };
        cb.onStart(mContext, paramUrl);
        QueueHelper.getInstance().addQueue(mContext, request);
    }

    @Override
    public void post(String url, UrlParams params, final RequestListener cb) {
        post(url, params, null, cb);
    }

    @Override
    public void post(String url, UrlParams params, Map<String, String> headerParams, final RequestListener cb) {
        SLog.e(HttpRequest.TAG, url);
        Request request;
        if (params != null && params.getFileParamList() != null && params.getFileParamList().size() > 0) {
            // 传文件+传表单
            request = new MultipartPostRequest(url, params, headerParams, new XResponseListener<String>(cb), new XErrorResponseListener(cb));
        } else {
            // 普通传表单
            request = new NormalPostRequest(url, params.getUrlParamMap(), headerParams, new XResponseListener<String>(cb), new XErrorResponseListener(cb));
        }
        cb.onStart(mContext, url);
        QueueHelper.getInstance().addQueue(mContext, request);
    }

    @Override
    public void post(String url, JSONObject jsonObject, final RequestListener cb) {
        post(url, jsonObject, null, cb);
    }

    @Override
    public void post(String url, JSONObject jsonObject, final Map<String, String> headParams, final RequestListener cb) {
        SLog.e(HttpRequest.TAG, url);
        JsonRequest<JSONObject> jsonRequest = new XJsonObjectRequest(Request.Method.POST, url, jsonObject, headParams,
                new XResponseListener<JSONObject>(cb), new XErrorResponseListener(cb)) {
        };
        cb.onStart(mContext, url);
        QueueHelper.getInstance().addQueue(mContext, jsonRequest);
    }


    @Override
    public void put(String url, JSONObject jsonObject, final RequestListener cb) {
        put(url, jsonObject, null, cb);
    }

    @Override
    public void put(String url, JSONObject jsonObject, final Map<String, String> headParams, final RequestListener cb) {
        SLog.e(HttpRequest.TAG, url);
        JsonRequest<JSONObject> jsonRequest = new XJsonObjectRequest(Request.Method.PUT, url, jsonObject, headParams,
                new XResponseListener<JSONObject>(cb), new XErrorResponseListener(cb)) {
        };
        cb.onStart(mContext, url);
        QueueHelper.getInstance().addQueue(mContext, jsonRequest);
    }


    @Override
    public void delete(String url, UrlParams params, RequestListener cb) {
        delete(url, params, null, cb);
    }

    @Override
    public void delete(String url, UrlParams params, final Map<String, String> headParams, RequestListener cb) {
        String paramUrl = UrlParams.getUrlWithQueryString(url, params);
        SLog.e(HttpRequest.TAG, paramUrl);
        StringRequest request = new StringRequest(Request.Method.DELETE, paramUrl, new XResponseListener<String>(cb), new XErrorResponseListener(cb)) {
            @Override
            public Map<String, String> getHeaders() throws AuthFailureError {
                HashMap<String, String> headers = new HashMap<String, String>();
                headers.put("Accept", "application/json");
                headers.put("Content-Type", "application/json; charset=UTF-8");
                if (headParams != null && headParams.size() > 0) {
                    headers.putAll(headParams);
                }
                return headers;
            }

            @Override
            protected Response<String> parseNetworkResponse(NetworkResponse response) {
                return ResponseHelper.parseNetworkResponse2String(response);
            }
        };
        cb.onStart(mContext, paramUrl);
        QueueHelper.getInstance().addQueue(mContext, request);
    }


    @Override
    public void finish() {
      /*  if (mRequest != null) {
            mRequest.cancel();
        } else {
            SLog.e(HttpRequest.TAG, "Cancel failed, no request exist!!!");
        }*/
    }


    /**
     * http response success
     *
     * @param response
     * @param cb
     */
    private void deliverResponse(String response, RequestListener cb) {
        SLog.e(HttpRequest.TAG, "function --> deliverResponse: msg == " + response);
        IResponseDataParser parser = cb.getResponseDataParser();
        if (cb != null) {
            if (parser != null && !TextUtils.isEmpty(response)) {
                parser.setJsonString(response);
                if (parser.isMyRules()) {
                    // 有些http数据的设计，虽然返回的http code是200， 但是仍然会把一部分错误的状态放在数据中。
                    if (parser.isSuccessful()) {
                        cb.onSuccess(parser.getData());
                    } else {
                        cb.onDeliverFailureResponse(new UnknownError(parser.getMessage()), parser.getCode(), parser.getMessage());
                    }
                    return;
                } else {
                    SLog.e(HttpRequest.TAG, "返回的数据不符合解析规则");
                    // http请求成功了，但是数据不符合解析规则。
                    cb.onSuccess(null);
                }
            } else {
                // http请求成功了，但是没有给数据。
                cb.onSuccess(null);
            }

        }
    }

    private void deliverErrorResponse(VolleyError error, RequestListener cb) {
        SLog.e(HttpRequest.TAG, "funtion --> deliverErrorResponse");
        if (cb != null) {
            String errorMsg = "";
            if (error != null && error.networkResponse != null && error.networkResponse.data != null) {
                errorMsg = new String(error.networkResponse.data);
            }
            int errorNo = -1;
            if (error != null && error.networkResponse != null) {
                errorNo = error.networkResponse.statusCode;
            }
            SLog.e(HttpRequest.TAG, "funtion --> onDeliverFailureResponse: msg == " + errorMsg + "  errorNo == " + errorNo);
            cb.onDeliverFailureResponse(error, errorNo, errorMsg);
        }
    }

    public class XResponseListener<T> implements Response.Listener<T> {
        RequestListener mListener;

        public XResponseListener(RequestListener cb) {
            mListener = cb;
        }

        @Override
        public void onResponse(T t) {
            String responseStr = null;
            if (t instanceof JSONObject) {
                JSONObject jobj = (JSONObject) t;
                if (jobj != null) {
                    responseStr = jobj.toString();
                }
            } else if (t instanceof String) {
                responseStr = (String) t;
            }
            deliverResponse(responseStr, mListener);
        }
    }


    public class XErrorResponseListener implements Response.ErrorListener {
        RequestListener mListener;

        public XErrorResponseListener(RequestListener cb) {
            mListener = cb;
        }

        @Override
        public void onErrorResponse(VolleyError volleyError) {
            deliverErrorResponse(volleyError, mListener);
        }
    }

}

